package com.hy.service.impl;


import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hy.admin.pojo.User;

import com.hy.dto.LoginDto;
import com.hy.exception.ZhentaoException;
import com.hy.mapper.UserMapper;
import com.hy.service.UserService;
import com.hy.system.LoginVo;
import com.hy.util.AuthContextUtil;
import com.hy.util.common.ResultCodeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
* @author Lenovo
* @description 针对表【user】的数据库操作Service实现
* @createDate 2025-03-04 19:18:34
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisTemplate<String , String> redisTemplate ;
    @Autowired
    private SysMenuServiceImpl sysMenuService;
    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);


    /**
     * 登录
     * @param loginDto
     * @return
     */
    @Override
    public LoginVo login(LoginDto loginDto) {
        log.info("开始登录流程 - 用户名: {}", loginDto.getUserName());

        // 校验验证码是否正确
        String captcha = loginDto.getCaptcha();
        String codeKey = loginDto.getCodeKey();
        log.info("验证码参数 - captcha: {}, codeKey: {}", captcha, codeKey);

        // 验证码参数检查
        if (StrUtil.isEmpty(captcha) || StrUtil.isEmpty(codeKey)) {
            log.warn("验证码参数为空 - captcha: {}, codeKey: {}", captcha, codeKey);
            throw new ZhentaoException(ResultCodeEnum.VALIDATECODE_ERROR, "验证码或验证码key不能为空");
        }

        // 从Redis中获取验证码
        String redisKey = "user:login:validatecode:" + codeKey;
        String redisCode = redisTemplate.opsForValue().get(redisKey);
        log.info("Redis验证码校验 - Key: {}, 存储的验证码: {}, 用户输入: {}",
            redisKey, redisCode, captcha.toLowerCase());

        // 验证码为空或已过期
        if (StrUtil.isEmpty(redisCode)) {
            log.warn("验证码不存在或已过期 - Key: {}", redisKey);
            throw new ZhentaoException(ResultCodeEnum.VALIDATECODE_ERROR, "验证码已过期");
        }

        // 验证码不匹配
        if (!redisCode.equals(captcha.toLowerCase())) {
            log.warn("验证码不匹配 - 期望值: {}, 实际值: {}", redisCode, captcha.toLowerCase());
            throw new ZhentaoException(ResultCodeEnum.VALIDATECODE_ERROR, "验证码错误");
        }

        // 验证通过删除redis中的验证码
        redisTemplate.delete(redisKey);
        log.info("验证码验证通过,已从Redis删除");

        // 根据用户名查询用户
        User sysUser = userMapper.selectByUserName(loginDto.getUserName());
        if(sysUser == null) {
            log.warn("用户不存在 - 用户名: {}", loginDto.getUserName());
            throw new ZhentaoException(ResultCodeEnum.LOGIN_ERROR, "用户名或密码错误");
        }
        log.info("用户存在 - 用户名: {}", loginDto.getUserName());

        // 验证密码（使用明文比较）
        String inputPassword = loginDto.getPassword();
        log.info("密码验证 - 用户: {}, 数据库密码: {}, 输入密码: {}",
            loginDto.getUserName(), sysUser.getPassword(), inputPassword);

        if(!inputPassword.equals(sysUser.getPassword())) {
            log.warn("密码不匹配 - 用户: {}", loginDto.getUserName());
            throw new ZhentaoException(ResultCodeEnum.LOGIN_ERROR, "用户名或密码错误");
        }
        // 登录成功后，设置用户信息到 AuthContextUtil
        AuthContextUtil.set(sysUser);

        // 生成令牌
        String token = UUID.randomUUID().toString().replace("-", "");
        String userJson = JSON.toJSONString(sysUser);
        log.info("生成token - 用户: {}, Token: {}", loginDto.getUserName(), token);

        // 保存到Redis
        try {
            redisTemplate.opsForValue().set("user:login:" + token, userJson, 30, TimeUnit.MINUTES);
            log.info("用户信息已保存到Redis - 用户: {}", loginDto.getUserName());
        } catch (Exception e) {
            log.error("Redis保存失败 - 用户: {}, 错误: {}", loginDto.getUserName(), e.getMessage());
            throw new ZhentaoException(ResultCodeEnum.LOGIN_ERROR, "登录失败，请重试");
        }

        // 构建响应结果
        LoginVo loginVo = new LoginVo();
        loginVo.setToken(token);
        loginVo.setRefresh_token("");

        log.info("登录成功 - 用户: {}", loginDto.getUserName());
        return loginVo;
    }

    @Override
    public User logout(String token) {
        String redisKey = "user:login:" + token;
        String userJson = redisTemplate.opsForValue().get(redisKey);

        if (StrUtil.isEmpty(userJson)) {
            log.warn("用户信息不存在或已过期 - Token: {}", token);
            return null;
        }

        User user = JSON.parseObject(userJson, User.class);
        if (user != null) {
            // 清除用户菜单缓存
            sysMenuService.clearUserMenuCache(String.valueOf(user.getId()));
            // 清除登录信息
            redisTemplate.delete(redisKey);
        }

        log.info("用户登出成功 - 用户ID: {}", user != null ? user.getId() : "null");
        return user;
    }
}




